package com.gwz.cardserver.service;

import com.gwz.cardserver.consts.MatchCodeConst;
import com.gwz.cardserver.consts.SocketConst;
import com.gwz.cardserver.dto.ReqBase;
import com.gwz.cardserver.dto.ResBase;
import com.gwz.cardserver.dto.match.MatchRoomDTO;
import com.gwz.cardserver.dto.room.MatchRoom;
import com.gwz.cardserver.entity.Account;
import com.gwz.cardserver.global.GlobalCache;
import com.gwz.cardserver.global.MatchCache;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;

@Service
@Slf4j
public class MatchService {
    @Autowired
    private GlobalCache globalCache;
    @Autowired
    private MatchCache matchCache;
    @Autowired
    private AccountService accountService;
    @Autowired
    private FightService fightService;



    public synchronized void ready(ChannelHandlerContext ctx, ReqBase reqBase) throws InterruptedException {
        Assert.isTrue(accountService.isOnline(ctx), ResBase.fall(reqBase, "玩家不在线"));
        String userId = globalCache.getUserIdBYChannel(ctx);
        Assert.isTrue(matchCache.isMatching(userId), ResBase.fall(reqBase, "用户没有房间"));
        MatchRoom room = matchCache.getRoom(userId);
        room.ready(userId);
        // 通知其他玩家准备
        ResBase readResBase = new ResBase();
        readResBase.setCode(SocketConst.MATCH);
        readResBase.setSubCode(MatchCodeConst.READY_BRO);
        readResBase.setResCode(200);
        readResBase.setResult(userId);
        room.brocast(readResBase, null);
        // 玩家是否全部准备完成
        if (room.isAllReady()) {


            ResBase resBase = new ResBase();
            resBase.setCode(SocketConst.MATCH);
            resBase.setSubCode(MatchCodeConst.START_PRO);
            resBase.setResCode(200);
            room.brocast(resBase, null);


            Thread.sleep(1000);
            // 开始战斗
            fightService.startFight(new ArrayList<>(room.getUids().keySet()));

            // 销毁房间
            matchCache.destory(room);
        }
        log.info("{}玩家准备了", userId);

    }

    public synchronized void leave(ChannelHandlerContext ctx, ReqBase reqBase) {
        Assert.isTrue(accountService.isOnline(ctx), ResBase.fall(reqBase, "玩家不在线"));


        String userId = globalCache.getUserIdBYChannel(ctx);
        if(matchCache.isMatching(userId) == false){
            return;
        }
        MatchRoom room = matchCache.leave(userId);
        ResBase resBase = new ResBase();
        resBase.setCode(SocketConst.MATCH);
        resBase.setSubCode(MatchCodeConst.LEAVE_BRO);
        resBase.setResCode(200);
        resBase.setResult(userId);
        room.brocast(resBase, ctx);
        log.info("{}玩家离开了", userId);
    }


    public synchronized MatchRoomDTO enter(ChannelHandlerContext ctx, ReqBase reqBase) {
        Assert.isTrue(accountService.isOnline(ctx), ResBase.fall(reqBase, "玩家不在线"));

        String userId = globalCache.getUserIdBYChannel(ctx);
        //FIXME 临时如果有匹配了
        //Assert.isTrue(!matchCache.isMatching(userId), ResBase.fall(reqBase, "此用户已在匹配队列"));
        if (matchCache.isMatching(userId)) {
            matchCache.leave(userId);
        }
        // 正常进入
        MatchRoom room = matchCache.enter(userId, ctx);
        // 广播给房间内所有用户,有新玩家加入了
        ResBase resBase = new ResBase();
        resBase.setCode(SocketConst.MATCH);
        resBase.setSubCode(MatchCodeConst.ENTER_BRO);
        resBase.setResCode(200);
        Account account = accountService.getById(ctx);
        resBase.setResult(account);
        room.brocast(resBase, ctx);

        log.info("{}玩家进入了房间", userId);

        return makeRoomDTO(room);
    }

    private MatchRoomDTO makeRoomDTO(MatchRoom matchRoom) {
        MatchRoomDTO matchRoomDTO = new MatchRoomDTO();
        matchRoomDTO.setId(matchRoom.getId());
        matchRoomDTO.setReadyUids(matchRoom.getReadyUids());
        ConcurrentHashMap<String, Account> accountConcurrentHashMap = new ConcurrentHashMap<>();
        matchRoom.getUids().forEach((k, v) -> {
            Account account = accountService.getById(v);
            accountConcurrentHashMap.put(k, account);
            matchRoomDTO.getUidList().add(k);
        });
        matchRoomDTO.setUids(accountConcurrentHashMap);
        return matchRoomDTO;
    }

    public void removeUserByChannel(ChannelHandlerContext channelHandlerContext) {
        ReqBase reqBase=new ReqBase();
        reqBase.setCode(SocketConst.MATCH);
        reqBase.setSubCode(MatchCodeConst.LEAVE);
        leave(channelHandlerContext,reqBase);
    }


}
